import random

from django.db import models
from game.common.common import FunctionField
from game.damage.models import damage
from game.common.logger import logger
from game.common.subclass import SubclassManager
from django.contrib.contenttypes.models import ContentType

#import game.monster.models

# Create your models here.

TARGET_TYPES= (
              (1, "Individual"),#Targets one individual
              (2, "Group"),     #Targets a single side in combat
              (3, "All"),       #Targets everyone in combat
              (4, "Self"),      #can only target the action user
              (5, "Random Friend"),
              (6, "Random Enemy"),
              (7, "Random All"),
              (8, "Random Group"),
              )

class action (models.Model):
    """
    An action is anything that can be done in combat
    """
    name = models.CharField(max_length = 255)
    speed = models.IntegerField(default = 10)
    mpNeeded = models.IntegerField(default = 0)
    actionPackage = 'game.actions.actionMethods'
    targetType = models.IntegerField(choices=TARGET_TYPES, default = 1)
    getSuccessMethod = models.CharField(max_length = 255)##FunctionField(package='game.actions.actionMethods')#, blank = True, null = True)
    successMethod = models.CharField(max_length = 255)#, blank = True, null = True)
    failureMethod = models.CharField(max_length = 255)#, blank = True, null = True)
    attemptMessage = models.CharField(max_length = 255, blank=True, null=True)
    successMessage =  models.CharField(max_length = 255, blank= True, null=True)
    failureMessage =  models.CharField(max_length = 255, blank= True, null=True)
    
    ##### Used for returning child objects
    content_type = models.ForeignKey(ContentType,editable=False,null=True)
    objects = SubclassManager()
    
    def save(self, *args, **kwargs):
        if(not self.content_type):
            self.content_type = ContentType.objects.get_for_model(self.__class__)
            super(action, self).save(*args, **kwargs)

    def as_leaf_class(self):
        content_type = self.content_type
        model = content_type.model_class()
        if (model == action):
            return self
        return model.objects.get(id=self.id)
    #####
    
    def getSuccess(self, caller, target):
        #determines if the action "hits" or "misses"
        #print dir(self.getSuccessMethod)
        #x = self.getSuccessMethod.to_python(caller, target)
        #logger.debug("Success method returned is %s" % x)
        x = __import__(self.actionPackage, fromlist=self.actionPackage)
        try:
            func = getattr(x, self.getSuccessMethod)
            logger.debug("getSuccess call: %s, returned: %s of type %s" % (self.getSuccessMethod, func,type(func) ) )
            results = func(caller, target)
            return results
        except AttributeError:
           # print value, """The function doesn't exist in the module"""
            return False
        except TypeError:
            print """Value isn't a string"""
            return False

    def onSuccess(self, caller, target):
        #what happens when the action hits
        x = __import__(self.actionPackage, fromlist=self.actionPackage)
        #try:
        func = getattr(x, self.successMethod)
        logger.debug("onSuccess call: %s, returned: %s of type %s" % (self.successMethod, func,type(func) ) )
        results = func(caller, target)
        return self.getSuccessMessage(caller, target)
        #except AttributeError:
           # print value, """The function doesn't exist in the module"""
         #   return False
        #except TypeError:
         #   print """Value isn't a string"""
          #  return False
                

    
    def onFailure(self, caller, target):
        #what happens when the action misses
        x = __import__(self.actionPackage, fromlist=self.actionPackage)
        try:
            func = getattr(x, self.failureMethod)
            logger.debug("onFailure call: %s, returned: %s of type %s" % (self.failureMethod, func,type(func) ) )
            results = func(caller, target)
            return self.getFailureMessage(caller, target)
        except AttributeError:
           # print value, """The function doesn't exist in the module"""
            return False
        except TypeError:
            print """Value isn't a string"""
            return False
                

    
    def getResults(self, caller, target):
        #performs the action and returns what happened. The individual performing the
        #action must be passed in as 'caller', the target of action must be passed as 'target'
        try:
            pass           
        except:
            raise
        
        if self.getSuccess(caller, target):
            #Action succeeds in hitting
            return self.onSuccess(caller, target)
        else:
            #Action misses
            return self.onFailure(caller, target)
    
    def getAttemptMessage(self, caller, target):
        return self.attemptMessage
    
    def getFailureMessage(self, caller, target):
        return self.failureMessage
    
    def getSuccessMessage(self, caller, target):
        return self.successMessage
    

class attack(action):
    """
    an attack generates damage of its given type based on the 
    the attack roll 
    """
    damageType = models.ForeignKey('damage.damageType')
    diceNum = models.IntegerField(default = 1)        #the numer of dice to roll
    diceSize = models.IntegerField(default = 1)       #the size of die to roll
    power = models.IntegerField(default = 1)          #to compare against defence
    objects = SubclassManager() 
    
    class Meta():
        abstract = False
        
    def __unicode__(self):
        return self.name
        
    def getDamage(self):
        """ Returns a damage object based off of the dice """
        totalDamage=0
        for x in range(0, self.diceNum):
            totalDamage += random.randint(1,self.diceSize)
        Damage = damage(
            damageType = self.damageType, power= self.power,
            amount = totalDamage)
        return Damage
        
    @property
    def damage(self):
        return self.getDamage()
